package rollercoaster.train.tests;

import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
import javax.media.opengl.awt.GLCanvas;
import javax.swing.JFrame;

import rollercoaster.commons.FixedStepTessellation;
import rollercoaster.commons.Node;
import rollercoaster.commons.interfaces.NodoProducer;
import rollercoaster.environment.utils.Shader;
import rollercoaster.train.BorderTextureCoordinateEvaluator;
import rollercoaster.train.ClassicCoachProducer;
import rollercoaster.train.interfaces.IMultipleSurfaceControlPointsReader;
import rollercoaster.train.interfaces.VagoneDataReader;
import rollercoaster.train.utils.OBJControlPointsMultipleSurfacesReader;
import rollercoaster.train.utils.XMLVagoneDataReader;

import com.jogamp.opengl.util.Animator;

public class DrawCoachWithProducerES {

	public static void main(String[] args) {
		JFrame frame=new JFrame();
		
		frame.setSize(1200,1200);
		frame.setTitle("Hello Universe");

		//Costruisco un GLEventListener
		GraphicsListener listener=new GraphicsListener();
		//Costruisco un GLCanvas
		GLProfile profile=GLProfile.getGL2ES2();
		GLCanvas canvas = new GLCanvas(new GLCapabilities(profile));
		//Associo il listener al canvas
		canvas.addGLEventListener(listener);
		//Il canvas  un componente grafico!! Posso aggiungerlo al Frame
		frame.getContentPane().add(canvas);
		Animator an = new Animator(canvas);
		an.start();
		
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);
	}
	
public static class GraphicsListener implements GLEventListener{
	/*	
	private static String vertexShader="" +
			"uniform mat4 transform;" +
			"attribute vec3 position;" +
			"attribute vec3 normal;" +
			"varying float light;" +
			"void main(){" +
			"	gl_Position=transform*vec4(position,1);" +
			"	light=dot(normal,vec3(0,0.6,0))+0.4;" +
			"}";
			*/
	private static String vertexShader="" +
			"uniform mat4 transform;" +
			"uniform mat2 textureTransform;"+
			"attribute vec3 position;" +
			"attribute vec3 normal;" +
			"attribute vec2 texcoord;"+
			"varying float light;" +
			"varying vec2 ftexcoord;"+
			"void main(){" +
			"	gl_Position=transform*vec4(position,1);" +
			"	vec3 normalVector=(transform*vec4(normal,0)).xyz;" +
			"	normalVector=normalize(normalVector);" +
			"	light=dot(normalVector,vec3(0,0.6,0.0))+0.8;" +
			"	ftexcoord=textureTransform*texcoord;"+
			"}";
	
		//texture2D(uSampler, vec2(ftexcoord.s, ftexcoord.t))+
		//+color*vec4(vec3(light),1);
		private static String fragmentShader="" +
				"uniform vec4 color;" +
				"uniform sampler2D uSampler;"+
				"varying float light;" +
				"varying vec2 ftexcoord;"+
				"void main(){" +
				"	gl_FragColor=texture2D(uSampler, vec2(ftexcoord.s, ftexcoord.t))*vec4(vec3(light),1)*color;" +
				"}";
				
		
		private Shader shader;
		private int attribObject;
		private int normalsAttribObject;
		private int textureAttribObject;
		private int uniformColor;
		private int uniformTransform;
		private int textureTransform;

		private Node nodo;
		private float t=0;
		
		
		/* Drawing method
		 * */
		public void display(GLAutoDrawable arg0) {
			
			//Take the gl elemnt
			GL2ES2 gl=(GL2ES2)arg0.getGL();
			
			gl.getGL2ES2();
			//Clear the image
			gl.glClearColor(1, 1, 1, 1);
			
			gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
			
			gl.glEnable(GL.GL_DEPTH_TEST);
			gl.glEnable(GL.GL_TEXTURE_2D);
			
			gl.glUseProgram(shader.getShadingProgram());
			
			gl.glUniform4f(uniformColor, 1f, 1f, 1f, 1);
			float scaleFactor=0.03f;
			t+=0.01f;
			float cos=(float)(Math.cos(0.2f+t));
			float sin=(float)(Math.sin(0.2f+t));
			
		/*
			float[] matrix={
					scaleFactor*cos,             0,    -scaleFactor*sin,     0,
					              0,   scaleFactor,                   0,     0,
					scaleFactor*sin,             0,     scaleFactor*cos,     0,
				                  0,             0,                   0,     1,
				};
		*/
		
			float[] matrix={
					scaleFactor*cos, 0, scaleFactor*sin,0,
					scaleFactor*sin,0,-scaleFactor*cos,0,
					0, scaleFactor, 0,0,
					0,0,0,1
			};
			
			
			nodo.setTransformMatrix(matrix);
			nodo.drawNode(gl);
		}
		
		public void dispose(GLAutoDrawable arg0) {
			// TODO Auto-generated method stub
			
		}

		/* init method
		 * */
		public void init(GLAutoDrawable arg0) {

			//Take the gl elemnt
			GL2ES2 gl=(GL2ES2)arg0.getGL();
			gl.getGL2ES2();
			shader=new Shader(fragmentShader, vertexShader);
			
			shader.compileShader(gl);
			
			//------- All this part should be done by the producer ----------- //
			
			VagoneDataReader textureReader=new XMLVagoneDataReader("trainModels/templateVagoneSpace.xml");
			IMultipleSurfaceControlPointsReader vertexReader=new OBJControlPointsMultipleSurfacesReader();
			FixedStepTessellation tess=new FixedStepTessellation(new BorderTextureCoordinateEvaluator());
			tess.setStep_u(0.1f);
			tess.setStep_v(0.1f);
			
			NodoProducer producer=new ClassicCoachProducer(textureReader, vertexReader, tess);
			nodo=producer.getNode(gl);

			//-------- END PRODUCER PART------//
			
			normalsAttribObject=gl.glGetAttribLocation(shader.getShadingProgram(), "normal");
			
			attribObject=gl.glGetAttribLocation(shader.getShadingProgram(), "position");
			
			textureAttribObject=gl.glGetAttribLocation(shader.getShadingProgram(), "texcoord");
			
			uniformColor=gl.glGetUniformLocation(shader.getShadingProgram(), "color");
			
			uniformTransform=gl.glGetUniformLocation(shader.getShadingProgram(), "transform");
			
			textureTransform=gl.glGetUniformLocation(shader.getShadingProgram(), "textureTransform");
			
			int[] shaderAttribs={attribObject,normalsAttribObject,textureAttribObject,textureTransform, uniformTransform};
			
			
			nodo.setShaderAttributes(shaderAttribs);
		
		}

		public void reshape(GLAutoDrawable arg0, int arg1, int arg2, int arg3, int arg4) {

		}
	}
	static final long serialVersionUID=100;
}
	
	

